﻿using System;
using System.Collections.Generic;
using System.Data.Common;

using DataAccess.Util;
using log4net;
using System.Reflection;

namespace DataAccess.SqlServer
{
    public class SqlEntityConverter<T> : IEntityConverter<T> where T : new()
    {
        private IValueTypeConverter convert = new SqlValueTypeConverter();

        /// <summary>
        /// Gets value form data reader then convert it to object.
        /// </summary>
        /// <param name="dr">data reader</param>
        /// <returns>entity object</returns>
        public virtual T Convert(DbDataReader dr)
        {
            return Convert(dr, convert);
        }

        /// <summary>
        /// Gets value form data reader then convert it to object.
        /// </summary>
        /// <param name="dr">data reader</param>
        /// <param name="convert">data convertor</param>
        /// <returns>entity object</returns>
        public virtual T Convert(DbDataReader dr, IValueTypeConverter convert)
        {
            ILog log = LogManager.GetLogger(this.GetType());

            T entity = new T();
            Dictionary<string, string> mapping = ReflectUtils.GetColumnMapping(typeof(T));

            foreach (KeyValuePair<string, string> pair in mapping)
            {
                try
                {
                    PropertyInfo propertyInfo = typeof(T).GetProperty(pair.Key);
                    propertyInfo.SetValue(entity, convert.Convert(propertyInfo.PropertyType, dr[pair.Value]), null);
                }
                catch (IndexOutOfRangeException)
                {
                    log.Warn(string.Format(DAConstants.ResultSetNotContain, pair.Value));
                }
                catch (Exception e)
                {
                    throw new Exception(string.Format(DAConstants.ConvertExceptionMessage, pair.Value, entity.GetType().Name, pair.Key, e.Message), e);
                }
            }

            return entity;
        }
    }
}
